home *** CD-ROM | disk | FTP | other *** search
/ Software 2000 / Software 2000 Volume 1 (Disc 1 of 2).iso / utilities / u130.dms / in.adf / SuperHop / superhop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-08-02  |  13.3 KB  |  418 lines

  1. #include <stdio.h>
  2. #include <exec/types.h>
  3. #include <intuition/intuition.h>
  4. #include <math.h>
  5. /***********************************************************************
  6. *  Superhop.c
  7. *
  8. *  This program opens a screen (using the XOpenScreen function),
  9. *  then requests four numbers as input.  The numbers are used to 
  10. *  generate a pattern as discussed in the August, 1986 Scientific 
  11. *  American article on computer recreations.  After a pattern is
  12. *  drawn, a portion of the pattern may be enlarged by selecting a
  13. *  box with the mouse.  To start a new pattern, change one or more
  14. *  of the input numbers.  To stop the program,
  15. *  select the close window gadget.  
  16. *
  17. *  Note: The XOpenScreen function is described in Compute!'s Amiga
  18. *  Programmer's Guide, and is not included here.  You'll have to 
  19. *  link with your own screen open function.
  20. *     Also, the inner-most loop uses the Motorola Fast Floating Point
  21. *  routines, which are difficult to use from Lattice.  The MyInit routine
  22. *  uses the usual C syntax, so if you want to compile with Manx, model 
  23. *  the inner-most loop after the MyInit formulae.
  24. *************************************************************************/
  25. #define DOWN  1
  26. #define UP    0
  27.  
  28. struct NewWindow newwindow = {
  29.      0,   0,
  30.    640, 200,
  31.      0,   1,
  32.    CLOSEWINDOW | MOUSEMOVE | MOUSEBUTTONS,
  33.    WINDOWSIZING | SIZEBRIGHT | WINDOWDEPTH | WINDOWDRAG
  34.       | SMART_REFRESH | ACTIVATE | NOCAREREFRESH
  35.       | WINDOWCLOSE | REPORTMOUSE,    
  36.    NULL,
  37.    NULL,
  38.    "Pattern Window",
  39.    NULL,
  40.    NULL,
  41.    180, 50, 640, 200,
  42.    CUSTOMSCREEN
  43. };
  44.  
  45. struct Window *window, *g_window;
  46. struct Screen *screen;
  47. struct GfxBase *GfxBase;   /* note: the name MUST be GfxBase */
  48. struct IntuitionBase *IntuitionBase;  /* as above */
  49. struct IntuiMessage *message;
  50. struct RastPort *DrawRP;
  51. struct RastPort *GadgRP;
  52. struct ViewPort *DrawVP;
  53. struct Screen *XOpenScreen();
  54.  
  55. BYTE scaled = 0;
  56.  
  57. void add_gadgets();
  58.  
  59. /* for Manx Aztec C */
  60. #if    MCH_AMIGA
  61. #include <functions.h>
  62. #endif
  63.  
  64. int MathBase;
  65. int MathTransBase;
  66.  
  67. typedef union { float f; int i; } FFP;
  68.  
  69. float SPTieee();
  70. char bmath[] = "mathffp.library";
  71. char tmath[] = "mathtrans.library";
  72.  
  73. char input[40] = "-3.14,.3,.3,10000";
  74. char outtext[40];
  75.  
  76. main()
  77. {
  78.    FFP affp, bffp, cffp, xscffp, xoffp, yoffp, f1ffp, xffp, yffp, xx, yy;
  79.    BYTE gadgflag = 1;     /* identifies when gadget window is on */
  80.    int color = 2;         /* drawing color */
  81.    int Depth = 4;         /* number of bit planes in screen */
  82.    int class, mcode;
  83.    FLOAT a, b, c;         /* parameters used in pattern algorithm */
  84.    FLOAT savea = 0, saveb = 0, savec = 0;  /* variables for saving a,b,c */
  85.    FLOAT f1 = 0.44;       /* scaling factor */
  86.    int i, num, dif;
  87.    int x0 = 0, y0 = 0;    /* location of dot to be drawn, in pixels */
  88.    FLOAT x = 0, y = 0;    /* location of dot to be drawn, in parameter space units */
  89.    FLOAT xoff = 0, yoff = 0, xscale = 0;  /* scale parameters */
  90.    FLOAT xmin, xmax, ymax, ymin;
  91.    int tlcx, tlcy;        /* top left corner of box */
  92.    int brcx, brcy;        /* bottom right corner of box */
  93.    int boxx, boxy = 0;    /* corners of box while being drawn */
  94.    BYTE boxon = 0;        /* flag for when a box is being drawn */ 
  95.   
  96. /* Open Libraries */ 
  97.    if ((IntuitionBase =
  98.          (struct IntuitionBase *)OpenLibrary("intuition.library",1)) == NULL)
  99.       Cleanup("Error: couldn't open intuition library\n");
  100.    if ((GfxBase =
  101.          (struct GfxBase *)OpenLibrary("graphics.library",1)) == NULL)
  102.       Cleanup("Error: couldn't open graphics library\n");
  103.    if ((MathBase = OpenLibrary(bmath,0)) == NULL) 
  104.       Cleanup("Error: couldn't open math library\n");
  105.    if ((MathTransBase = OpenLibrary(tmath,0)) == NULL) 
  106.       Cleanup("Error: couldn't open math transform library\n");
  107.  
  108.    if ((screen =
  109.          (struct Screen *)XOpenScreen("Simple Screen", HIRES, Depth)) == NULL)
  110.       Cleanup("Error: couldn't open custom screen\n");
  111.    newwindow.Screen = screen;
  112.    if ((window = (struct Window *)OpenWindow(&newwindow)) == NULL)
  113.       Cleanup("Error: couldn't open window\n");
  114.    DrawRP = window->RPort;
  115.    DrawVP = &screen->ViewPort;
  116. reset:
  117.    gadgflag = 1;
  118.    add_gadgets(screen);
  119. /*   setcolors(DrawVP,colors); (A function to replace all this...) */
  120.    SetRGB4(DrawVP, 0, 0, 0, 0);
  121.    SetRGB4(DrawVP, 1, 15, 15, 15);
  122.    SetRGB4(DrawVP, 2, 15, 0, 0);
  123.    SetRGB4(DrawVP, 3, 0, 15, 0);
  124.    SetRGB4(DrawVP, 4, 14, 3, 0);
  125.    SetRGB4(DrawVP, 5, 15, 11, 0);
  126.    SetRGB4(DrawVP, 6, 15, 15, 2);
  127.    SetRGB4(DrawVP, 7, 15, 15, 15);
  128.    SetRGB4(DrawVP, 8, 7, 13, 15);
  129.    SetRGB4(DrawVP, 9, 11, 15, 0);
  130.    SetRGB4(DrawVP, 10, 5, 13, 0);
  131.    SetRGB4(DrawVP, 11, 12, 0, 14);
  132.    SetRGB4(DrawVP, 12, 15, 2, 14);
  133.    SetRGB4(DrawVP, 13, 15, 4, 10);
  134.    SetRGB4(DrawVP, 14, 15, 6, 6);
  135.    SetRGB4(DrawVP, 15, 15, 8, 2);
  136.    SetAPen(DrawRP, color);
  137.    SetDrMd(DrawRP, JAM2);
  138.  
  139. /* Is the gadget window showing? */
  140.  
  141.    while (gadgflag) {
  142. /* Wait for something to happen. */
  143.       Wait((1<<window->UserPort->mp_SigBit) | 
  144.               (1<<g_window->UserPort->mp_SigBit));
  145.       while (message = (struct IntuiMessage *)GetMsg(window->UserPort)) {
  146. /* Something happened in the main pattern window. */
  147.          class = message->Class;
  148.          switch (class) {
  149.             case CLOSEWINDOW:         /* We are all done */
  150.                ReplyMsg(message);
  151.                Cleanup(NULL);
  152.             case MOUSEBUTTONS:
  153.                mcode = message->Code;
  154.            if(mcode == SELECTDOWN) { /* The user wants to set the TLC */
  155.               if(xoff == 0) break;
  156.                   tlcx = message->MouseX;
  157.                   tlcy = message->MouseY;
  158.                   boxon = 1;
  159.                   boxx = -1;
  160.                   SetDrMd(DrawRP,COMPLEMENT);
  161.                }
  162.                else if(mcode == SELECTUP) { /* The user has defined the box */
  163.                   Move(DrawRP,tlcx,tlcy);   /* redraw (erase) old box */
  164.                   Draw(DrawRP,tlcx,boxy);
  165.                   Draw(DrawRP,boxx,boxy);
  166.                   Draw(DrawRP,boxx,tlcy);
  167.                   Draw(DrawRP,tlcx,tlcy);
  168.                   brcx = message->MouseX;
  169.                   brcy = message->MouseY;
  170.                   SetDrMd(DrawRP,JAM2);
  171.                   boxon = 0;
  172.                   xmax = ((float) (brcx-320.)/xscale) + xoff;
  173.                   xmin = ((float) (tlcx-320.)/xscale) + xoff;
  174.                   ymax = ((float) (brcy-100.)/(f1*xscale)) + yoff;
  175.                   ymin = ((float) (tlcy-100.)/(f1*xscale)) + yoff;
  176.                   x = 0;
  177.                   y = 0;
  178.                   xscale = 640./(xmax - xmin);
  179.                   xoff = (xmax + xmin)/2.;
  180.                   yoff = (ymax + ymin)/2.;
  181.                   scaled = 1;
  182.                     SetAPen(DrawRP,0);
  183.                   RectFill(DrawRP,0,0,640,200);
  184.                }
  185.                break;
  186.             case MOUSEMOVE:           /* If boxon, draw box, else ignore */
  187.                if(boxon) {
  188.                   if(boxx >= 0) {
  189.                      Move(DrawRP,tlcx,tlcy);   /* redraw (erase) old box */
  190.                      Draw(DrawRP,tlcx,boxy);
  191.                      Draw(DrawRP,boxx,boxy);
  192.                      Draw(DrawRP,boxx,tlcy);
  193.                      Draw(DrawRP,tlcx,tlcy);
  194.                   }
  195.                   boxx = message->MouseX;
  196.                   boxy = message->MouseY;
  197.                   Move(DrawRP,tlcx,tlcy);   /* draw new box */
  198.                   Draw(DrawRP,tlcx,boxy);
  199.                   Draw(DrawRP,boxx,boxy);
  200.                   Draw(DrawRP,boxx,tlcy);
  201.                   Draw(DrawRP,tlcx,tlcy);
  202.                }
  203.                break;
  204.          }
  205.          ReplyMsg(message);
  206.       }
  207.       while (message = (struct IntuiMessage *)GetMsg(g_window->UserPort)) {
  208. /* Something happened in the gadget window. */
  209.            if (message->Class == GADGETUP) {
  210.               if (sscanf(input,"%f,%f,%f,%d", &a, &b, &c, &num) != 4) {
  211.                   sprintf(input,"Error scanning input.  Reenter.");
  212.                   Move(GadgRP,10,20);
  213.                   Text(GadgRP,input,sizeof(input));
  214.               } 
  215.               else {
  216.                  if(savea != a || saveb != b || savec != c) {
  217. /* At least one of the inputs has changed.  Reset everything. */
  218.                     x = 0;
  219.                     y = 0;
  220.                     SetAPen(DrawRP,0);
  221.                   RectFill(DrawRP,0,0,640,200); /* erases screen */
  222.                   scaled = 0;
  223.                  } 
  224.                  gadgflag = 0;
  225.                savea = a;
  226.                saveb = b;
  227.                savec = c;
  228.               }
  229.            }
  230.            ReplyMsg(message);
  231.       }
  232.    }
  233.  
  234.    if (g_window) CloseWindow(g_window);
  235.    g_window = NULL;
  236.    myInit(a, b, c, &xscale, &xoff, &yoff);
  237.    dif = num/12;
  238.  
  239. /* This is the main loop.  Everything in here should be FFP or integer */
  240. /* First load up FFP variables. */
  241.    affp.f = a;
  242.    bffp.f = b;
  243.    cffp.f = c;
  244.    xscffp.f = xscale;
  245.    xoffp.f = xoff;
  246.    yoffp.f = yoff;
  247.    f1ffp.f = f1;
  248.    xffp.f = x;
  249.    yffp.f = y; 
  250.    affp.i = SPFieee(affp.i);
  251.    bffp.i = SPFieee(bffp.i);
  252.    cffp.i = SPFieee(cffp.i);
  253.    xffp.i = SPFieee(xffp.i);
  254.    yffp.i = SPFieee(yffp.i);
  255.    xscffp.i = SPFieee(xscffp.i);
  256.    xoffp.i = SPFieee(xoffp.i);
  257.    yoffp.i = SPFieee(yoffp.i);
  258.    f1ffp.i = SPFieee(f1ffp.i);
  259.    
  260. /* Now do loop */
  261.    for (i = 1; i < num; i++) {
  262.       color = (i/dif)+4;
  263.       SetAPen(DrawRP,color);
  264.       x0 = 320 + (int) SPTieee(SPMul(SPSub(xoffp.i,xffp.i),xscffp.i));
  265.       y0 = 100 + (int) SPTieee(SPMul(SPMul(f1ffp.i,xscffp.i),
  266.                                SPSub(yoffp.i,yffp.i)));
  267.       WritePixel(DrawRP, x0, y0);
  268.       xx.i = SPSub( SPMul(Sign(xffp.i), SPSqrt(SPAbs(
  269.                   SPSub(cffp.i,SPMul(bffp.i,xffp.i))))),yffp.i);
  270.       yy.i = SPSub(xffp.i,affp.i);
  271.       xffp.i = xx.i;
  272.       yffp.i = yy.i;
  273.       while (message = (struct IntuiMessage *)GetMsg(window->UserPort)) {
  274.          if (message->Class == CLOSEWINDOW) {
  275.             ReplyMsg(message);
  276.             Cleanup(NULL);
  277.          }
  278.          ReplyMsg(message);
  279.       }
  280.    }  
  281. /* Done with loop, now convert final x, y from FFP to float */
  282.    x = SPTieee(xffp.i);
  283.    y = SPTieee(yffp.i);   
  284.    goto reset;        
  285. }
  286.  
  287. Sign(x)
  288. /* The sign bit of an FFP number is in bit 7.  It is 0 for positive,
  289.    and 1 for negative. */
  290. int x;
  291. {
  292.    FFP xp;
  293.    BYTE signbit;
  294.    
  295.    signbit = (x & 0x80L) >> 7;
  296.    if (signbit) {
  297.       xp.f = -1;
  298.       xp.i = SPFieee(xp.i);
  299.    } else {
  300.       xp.f = 0;
  301.       xp.i = SPFieee(xp.i);
  302.    }
  303.    return(xp.i);     /* Returns as integer, but will be interpreted as FFP */
  304. }
  305.  
  306. Sign2(x)
  307.  
  308. float x;
  309. {
  310.    int i;
  311.    
  312.    i = (x >= 0) ?  1 : -1 ;
  313.    return(i);
  314. }
  315.   
  316. myInit(a, b, c, xscale, xoff, yoff)
  317. /********************************************************************
  318.  *   This routine calculates the first 100 points and keeps track   *
  319.  *   of the highest and lowest x and y values, then uses them for   *
  320.  *   setting the scale of the screen.  The screen is scaled so that *
  321.  *   the pattern takes up the middle quarter of the screen.  The    *
  322.  *   x scale is returned in *xscale, and the world coordinate       *
  323.  *   values of the center of the screen are returned as *xoff and   * 
  324.  *   *yoff.                                *
  325.  *******************************************************************/ 
  326. FLOAT a, b, c;
  327. FLOAT *xscale, *xoff, *yoff;
  328. {
  329.    int i;
  330.    FLOAT ymax = -1.e10, ymin = 1.e10;
  331.    FLOAT xmax = -1.e10, xmin = 1.e10;
  332.    FLOAT x = 0, y = 0;
  333.    FLOAT xx = 0, yy = 0;
  334.  
  335.    if(scaled) return(0);
  336.    for (i = 0; i < 100; i++) {
  337.       xx = y - (FLOAT) Sign2(x) * sqrt(abs(b * x - c));
  338.       yy = a - x;
  339.       xmax = (xx > xmax) ? xx : xmax;
  340.       xmin = (xx < xmin) ? xx : xmin;
  341.       ymax = (yy > ymax) ? yy : ymax;
  342.       ymin = (yy < ymin) ? yy : ymin;
  343.       x = xx;
  344.       y = yy;
  345.    }
  346. /*  These are the world coordinates of the center of the screen.  */
  347.    *xoff = (xmax + xmin)/2.;
  348.    *yoff = (ymax + ymin)/2.;
  349.    *xscale = 210./(xmax - xmin);
  350. /*   These are for diagnostics only...
  351.    SetAPen(DrawRP,4);
  352.    sprintf(outtext,"xx = %f, xn = %f, yx = %f, yn = %f",xmax,xmin,ymax,ymin);
  353.    Move(DrawRP, 10, 100);
  354.    Text(DrawRP,outtext,sizeof(outtext));
  355.    sprintf(outtext,"xo=%f, yo=%f, xsc=%f",*xoff,*yoff,*xscale);
  356.    Move(DrawRP, 10, 110);
  357.    Text(DrawRP,outtext,sizeof(outtext));
  358. */
  359.    return(0);
  360. }
  361.  
  362.  
  363. Cleanup (ExitText)
  364.  
  365. char *ExitText;
  366. {
  367.    if (g_window) CloseWindow(g_window);
  368.    if (window) CloseWindow(window);
  369.    if (screen) CloseScreen(screen);
  370.    if (GfxBase) CloseLibrary(GfxBase);
  371.    if (MathBase) CloseLibrary(MathBase);
  372.    if (MathTransBase) CloseLibrary(MathTransBase);
  373.    if (ExitText) fprintf(stderr, ExitText);
  374.    exit (!!ExitText);   /* NULL returns 0, all else returns 1 */
  375. }
  376.  
  377. void add_gadgets(Screen)
  378.  
  379. /* Open gadget window, complete with string gadget. */
  380.  
  381. struct Screen *Screen;
  382. {
  383.    static char undo[40] = "";
  384.  
  385.    static struct IntuiText help_text = {
  386.       0, 1, JAM2,
  387.       4, -10, NULL,
  388.       "Enter four numbers a, b, c, num",
  389.       NULL
  390.    };
  391.  
  392.    static struct StringInfo hslstring   = {
  393.       input, undo,             /* input string and undo string */
  394.       0, sizeof(input),        /* initial and max cursor position */
  395.       0,                       /* position of first displayed char */
  396.       0, 0, sizeof(input), 0, 0, NULL, 0, NULL
  397.    };
  398.  
  399.    static struct Gadget input_gadget = {
  400.       NULL, 10, 20, 320, 10, GADGHCOMP,
  401.       RELVERIFY, STRGADGET, NULL, NULL,
  402.       &help_text, NULL, (APTR)&hslstring, 0, NULL
  403.    };
  404.  
  405.    static struct NewWindow gadget_window = {
  406.       100, 50, 420, 30, -1, -1, GADGETUP | GADGETDOWN,
  407.       WINDOWDEPTH | WINDOWDRAG | SMART_REFRESH,
  408.       &input_gadget, NULL, "Input", 
  409.       NULL, NULL, 0, 0, 0, 0,
  410.       CUSTOMSCREEN
  411.    };
  412.  
  413.    gadget_window.Screen = Screen;
  414.    if ((g_window = (struct Window *)OpenWindow(&gadget_window)) == NULL)
  415.       Cleanup("Could not open gadget window.");
  416. }
  417.  
  418.